package com.xnew.utils;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.xnew.Reflection.ReflectionHelper;
import com.xnew.bean.common.DictionaryInfo;
import com.xnew.constant.Constant;
import com.xnew.exception.CustomException;

import java.lang.reflect.Field;
import java.util.*;

public class ConvertEntityUtil {

    /**
     * 根据传进的数据及实体类名称，反射获取该实体类需要转码的属性及类型，将数据转码后返回
     * @param data 需要转码的结果集
     * @return Object 转换后的数据
     * */
    public static Object convertEntityData(Object data) throws Exception {
        if(data!= null){

        Class clazz = data.getClass();
        try{
            String[] includeField = (String[]) ReflectionHelper.invokeClassMethod(data, "buildIncludeField");//反射调用实体类的buildIncludeField方法获取需要转换的属性
            String[] includeType  = (String[]) ReflectionHelper.invokeClassMethod(data, "buildIncludeType");//反射调用实体类的buildIncludeField方法获取需要转换的属性对呀的数据字典类型
            if(null != includeField && includeField.length !=0 && includeField.length == includeType.length){
                for(int i=0; i< includeField.length; i++){
                    Field field = clazz.getDeclaredField(includeField[i]);//反射获取属性
                    field.setAccessible(true);//设置私有变量可操作
                    if("OBJECT".equals(includeType[i])){
                        convertEntityData(field.get(data));
                    }else if("LIST".equals(includeType[i])){
                        List list = (List) field.get(data);
                        if(list != null){
                            convertListData(list);
                        }
                    }else{
                        Field dictNameResult = clazz.getDeclaredField("dictNameResult");//反射获取dictNameResult属性
                        if(dictNameResult != null){
                            dictNameResult.setAccessible(true);//设置私有变量可操作
                            Map<String, Object> map = (Map<String, Object>) dictNameResult.get(data);
                            map.put(includeField[i]+"_type", includeType[i]);
                            map.put(includeField[i], getRedisValueByTypeAndKey(field.get(data), includeType[i]));//将转换后结果放到Map对象中
                            dictNameResult.set(data, map);//重置dictNameResult属性值
                        }

                    }
                }
            }
        }catch (Exception e) {

        }
        }

        return data;
    }



    /**
     * 根据传进的数据集合及实体类名称，反射获取该实体类需要转码的属性及类型，将数据转码后返回
     * @param list 需要转码的结果集
     * @return Object 转换后的数据
     * */
    public static List<Object> convertListData(List list)  {
        try {
            for(int i=0; i< list.size(); i++){
                list.set(i, convertEntityData(list.get(i)));
            }
            return list;
        }catch (Exception e)
        {
            e.printStackTrace();
            throw new CustomException(500,"返回数据转码失败");
        }

    }

    /**
     * 根据传进的数据及实体类名称，反射获取该实体类需要转码的属性及类型，将数据转码后返回
     * @param key 需要转换的值
     * @param type 数据字典类型
     * @return Object 转换后的值
     * */
    public static Object getRedisValueByTypeAndKey(Object key, String type) throws Exception {
        String redisKey = RedisUtil.buildKey(":", new String[]{Constant.SYSTEM_NAME, Constant.DICT_TYPE});
        if(null == key || "".equals(key.toString())){
            return key;
        }
        if(!Constant.USER_NAME.equals(type) && !Constant.ORG_NAME.equals(type) && !Constant.ORG_ALL_NAME.equals(type)){
            String result = RedisUtil.get(RedisUtil.buildKey(":", new String[]{redisKey, type}));
            if(null == result || "".equals(result)){
                return key;
            }
            List<JSONObject> typeValueList = JSONObject.parseObject(result, List.class);
            if(null == typeValueList || typeValueList.size() == 0){
                return key;
            }
            for(int i=0; i<typeValueList.size(); i++){
                DictionaryInfo dictionaryInfo = JSONObject.toJavaObject(typeValueList.get(i), DictionaryInfo.class);
                if(key.toString().equals(dictionaryInfo.getCode())){
                    return dictionaryInfo.getName();
                }
            }
            return key;
        }else{
            if(Constant.USER_NAME.equals(type)){
                redisKey = RedisUtil.buildKey(":", new String[]{Constant.SYSTEM_NAME, Constant.USER_NAME});
            }else if(Constant.ORG_NAME.equals(type)){
                redisKey = RedisUtil.buildKey(":", new String[]{Constant.SYSTEM_NAME, Constant.ORG_NAME});
            }else if(Constant.ORG_ALL_NAME.equals(type)){
                redisKey = RedisUtil.buildKey(":", new String[]{Constant.SYSTEM_NAME, Constant.ORG_ALL_NAME});
            }
            redisKey = RedisUtil.buildKey(":", new String[]{Constant.SYSTEM_NAME, Constant.USER_ORG_TYPE});
            String value = RedisUtil.get(RedisUtil.buildKey(":", new String[]{redisKey, type, key.toString()}));
            if(null == value || "".equals(value)){
                return key;
            }
            return value;
        }
    }

    /**
     * 根据传进的数据及实体类名称，反射生成实体数据
     * @param param 参数内容
     * @return Object 转换后的值
     * */
    public static Object convertEntityByParam(Map param, Object data)  throws RuntimeException {
     try {
         Field[] fields = data.getClass().getDeclaredFields();
         for(Field field: fields){
             field.setAccessible(true);//设置私有变量可操作
             Object value = param.get(field.getName());
             if(value == null){
                 continue;
             }
             try {
                 field.set(data,value);
             }catch (Exception e)
             {
                 e.printStackTrace();
             }

         }
         return data;
     }
     catch (Exception e)
     {
         throw  new CustomException(500,"参数解析失败");
     }
    }


    /**
     * 组装字典对象
     * @param object 数据源 应该是个map 或者json都行 对象也行 不过就需要有相应的字段
     * @param key  字典值的字段
     * @param tokey 字典信息要存到什么字段 存的是个json 有code 和name
     * @param id   字典的id
     */
    public static void convertDictionaryInfoOne(Object object,String key,String tokey,String id)
    {
        ArrayList<Object> list = new ArrayList<>();
        list.add(object);
        convertDictionaryInfo(list,key,tokey,id);
    }

    /**
     * 组装字典对象
     * @param list 数据源 应该是个list里面是个map 或者json都行
     * @param key  字典值的字段
     * @param tokey 字典信息要存到什么字段 存的是个json 有code 和name
     * @param id   字典的id
     */
    public static void convertDictionaryInfo(Collection<Object> list,String key,String tokey,String id) {

        try {
            //从redis中获取字典映射关系
            Map<String, JSONObject> dictionaryInfoMap = getDictionaryInfoMap(id);

            //循环列表进行赋值
            for (Object info:list ) {
                //判断是不是一个map对象
                if(info instanceof Map)
                {
                    //map对象进行填装数据
                    Map map = (Map)info;
                    Object o = map.get(key);
                    JSONObject object = dictionaryInfoMap.get(o);
                    map.put(tokey,object);
                }
                else{
                    //如果不是map对象 就应该是字段赋值了
                    Field field = info.getClass().getField(key);
                    Field tofile = info.getClass().getField(tokey);
                    //如果来源或者赋值的地方为空 则不可能使用
                    if(field==null || tofile==null)
                    {
                        continue;
                    }
                    Object o = field.get(info);
                    JSONObject object = dictionaryInfoMap.get(o);
                    tofile.set(tofile,object);
                }

            }
        }catch (Exception e)
        {
            throw  new CustomException(500,"回传值 组装数据错误");
        }
    }
    //通过id获取字典的map
    private  static Map<String,JSONObject> getDictionaryInfoMap(String id)
    {

        String redisKey = RedisUtil.buildKey(":", new String[]{Constant.SYSTEM_NAME, Constant.DICT_TYPE,id});
        String result = RedisUtil.get(redisKey);
        if(null == result || "".equals(result)){
            return new HashMap<>();
        }
        List<JSONObject> typeValueList = JSONObject.parseObject(result, List.class);
        if(null == typeValueList || typeValueList.size() == 0){
            return new HashMap<>();
        }
        Map<String,JSONObject> map = new HashMap<>();

        for(int i=0; i<typeValueList.size(); i++){
            DictionaryInfo dictionaryInfo = JSONObject.toJavaObject(typeValueList.get(i), DictionaryInfo.class);
            JSONObject value = new JSONObject();
            value.put("code",dictionaryInfo.getCode());
            value.put("name",dictionaryInfo.getName());
            map.put(dictionaryInfo.getCode() , value);
        }
        return  map;
    }



}
